from sqlalchemy import Column, Integer, String, Boolean, Float, ForeignKey, desc, SmallInteger, orm, Text
from sqlalchemy.orm import relationship
from werkzeug.security import generate_password_hash, check_password_hash

from app.libs.error_code import NotFount, AuthFailed
from app.models.base import Base, db


#
# class Apis(Base):
#     id = Column(Integer, primary_key=True)
#     api_name=Column(String(50),nullable=False, unique=True) #接口名称唯一，后续要个参数表，根据接口名称传递参数
#     request_method=Column(String(50),nullable=False)
#     path=Column(String(50),nullable=False)
#     headers=Column(String(2000))
#     parameter=Column(String(1000))
#     scene_type=Column(Integer)  #场景类型 0是单接口测试   1是业务场景多接口测试
#     execution_sequence=Column(Integer) #业务场景多接口执行顺序
#     is_depend=Column(Integer) #是否需要依赖，依赖 0是不需要 1是依赖请求参数 2是依赖响应参数
#     depend_api_name=Column(String(50)) #被依赖的接口名称
#     depend_field=Column(Text)#需要依赖的字段
#     depend_expression=Column(Text) #提取依赖字段的表达式
#     asserts_expression=Column(String(1000)) #断言表达式
#     asserts_result=Column(Integer)
#     return_parameters=Column(Text,nullable=False)
#     all_parameters=Column(Text,nullable=False)
#     @staticmethod
#     def add_apis(api_name, request_method, path,headers,parameter,scene_type,execution_sequence,is_depend,depend_api_name,asserts_expression,asserts_result,return_parameters,all_parameters):
#         with db.auto_commit():
#             apis = Apis()
#             apis.api_name = api_name
#             apis.request_method = request_method
#             apis.path = path
#             apis.headers = headers
#             apis.parameter = parameter
#             apis.scene_type=scene_type
#             apis.execution_sequence = execution_sequence
#             apis.is_depend = is_depend
#             apis.depend_api_name=depend_api_name
#             apis.asserts_result = asserts_result
#             apis.return_parameters=return_parameters
#             apis.asserts_expression=asserts_expression
#             apis.all_parameters=all_parameters
#             db.session.add(apis)

# 接口信息表
class Apis(Base):
    id = Column(Integer, primary_key=True)
    api_name = Column(String(50), nullable=False, unique=True)  # 接口名称唯一，后续要个参数表，根据接口名称传递参数
    request_method = Column(String(50), nullable=False)
    path = Column(String(50), nullable=False)
    headers = Column(Text)
    parameter = Column(Text)
    asserts_expression = Column(String(1000))  # 断言表达式
    return_parameters = Column(Text, nullable=False)

    @orm.reconstructor
    def __init__(self):
        self.fields = ['id', 'api_name', 'request_method', 'path', 'headers', 'parameter', 'asserts_expression',
                       'return_parameters','create_time']
    @staticmethod
    def add_apis(api_name, request_method, path, headers, parameter, asserts_expression, return_parameters):
        with db.auto_commit():
            apis = Apis()
            apis.api_name = api_name
            apis.request_method = request_method
            apis.path = path
            apis.headers = headers
            apis.parameter = parameter
            apis.asserts_expression = asserts_expression
            apis.return_parameters = return_parameters
            db.session.add(apis)


# 场景表
class Scene(Base):
    id = Column(Integer, primary_key=True)
    scene_name = Column(String(50), nullable=False, unique=True)
    api_name_list = Column(Text, nullable=False)

    @orm.reconstructor
    def __init__(self):
        self.fields = ['id', 'scene_name', 'api_name_list','create_time']
    @staticmethod
    def add_scene(scene_name, api_name_list):
        with db.auto_commit():
            scene = Scene()
            scene.scene_name = scene_name
            scene.api_name_list = api_name_list
            db.session.add(scene)


"""一对多关系中，在多的一方定义外键，关系可在任一方定义
这是关系backref后面写当前类的小写类名
    scenes=relationship("Scene", backref='apisscene')
    apis=relationship("Apis", backref='apisscene')
这是外键 ApisScene 对象可以点apis得到 Apis对象，然后得到直接记录的接口的参数
    scene_id = Column(Integer, ForeignKey('scene.id'))
    api_id = Column(Integer, ForeignKey('apis.id'))
"""


# 接口场景表(根据场景表里面的接口名称列表写入接口表的id)
class ApisScene(Base):
    id = Column(Integer, primary_key=True)
    scene_id = Column(Integer, ForeignKey('scene.id'))
    api_id = Column(Integer, ForeignKey('apis.id'))
    api_name = Column(String(50))
    path = Column(Text)
    request_method = Column(Text)
    request_parameter = Column(Text)
    is_depend = Column(Integer)  # 是否需要依赖，依赖 0是不需要 1是需要
    depend_api_name = Column(String(50))  # 被依赖的接口名称
    depend_replace = Column(Text)  # 需要依赖的字段
    asserts_expression = Column(String(1000))
    scenes = relationship("Scene", backref='apisscene')
    apis = relationship("Apis", backref='apisscene')

    @orm.reconstructor
    def __init__(self):
        self.fields = ['id', 'api_name', 'path', 'create_time','request_method','request_parameter','is_depend','depend_api_name','depend_replace','asserts_expression']

    @staticmethod
    def add_apis_scene(scene_id, api_id, api_name, path, request_method, request_parameter, depend_api_name,
                       depend_replace,
                       asserts_expression):
        with db.auto_commit():
            apis_scene = ApisScene()
            apis_scene.scene_id = scene_id
            apis_scene.api_id = api_id
            apis_scene.api_name = api_name
            apis_scene.request_parameter = request_parameter
            apis_scene.depend_api_name = depend_api_name
            apis_scene.depend_replace = depend_replace
            apis_scene.asserts_expression = asserts_expression
            apis_scene.path = path
            apis_scene.request_method = request_method
            db.session.add(apis_scene)


# 接口场景执行记录表
class ApiExecutiveLogging(Base):
    id = Column(Integer, primary_key=True)
    scene_id = Column(Integer, ForeignKey('scene.id'))
    scene_name = Column(String(50), nullable=False)
    apis_id = Column(Integer, ForeignKey('apis.id'))
    api_name = Column(String(50))
    ip = Column(String(50))
    path = Column(String(1000))
    headers = Column(Text)
    request_method = Column(String(10), nullable=False)
    request_parameter = Column(Text)
    asserts_expression = Column(String(1000))
    asserts_result = Column(Integer)
    return_parameters = Column(Text, nullable=False)
    depend_replace = Column(Text)

    @orm.reconstructor
    def __init__(self):
        self.fields = ['id', 'scene_id', 'scene_name', 'apis_id', 'api_name', 'ip', 'path',
                       'headers', 'request_method', 'request_parameter','asserts_expression','asserts_result','return_parameters','depend_replace','create_time']
    @staticmethod
    def add_log(scene_id, scene_name, api_id, api_name, ip, path, headers, request_method, depend_replace,
                request_parameter, depend_api_name, asserts_result, asserts_expression,return_parameters):
        with db.auto_commit():
            log = ApiExecutiveLogging()
            log.scene_id = scene_id
            log.apis_id = api_id
            log.api_name = api_name
            log.request_parameter = request_parameter
            log.depend_api_name = depend_api_name
            log.depend_replace = depend_replace
            log.asserts_expression = asserts_expression
            log.path = path
            log.request_method = request_method
            log.scene_name = scene_name
            log.return_parameters=return_parameters
            log.ip = ip
            log.headers = headers
            log.asserts_result = asserts_result
            db.session.add(log)


class Config(Base):
    id = Column(Integer, primary_key=True)
    ip = Column(String(50))
    ip_name=Column(String(50))
    use=Column(Integer,default=0)
    @orm.reconstructor
    def __init__(self):
        self.fields = ['id', 'ip', 'ip_name', 'use','create_time']
    @staticmethod
    def add_config(ip, ip_name):
        with db.auto_commit():
            config = Config()
            config.ip = ip
            config.ip_name = ip_name
            db.session.add(config)

    @staticmethod
    def use_0(id):
        config=Config.query.filter().all()
        for i in config:
            i.use=0
        Config.query.get(id).use=1
        db.session.commit()
